/*************************************************************************************
 * Nombre del archivo: Generador_Analizador_lexico.java
 * Universidad del Valle de Guatemala
 * Curso: Diseño de Lenguajes de Programación
 * @author martin
 *          Martín Guzmán 08041
 * Fecha: Abril de 2010
 * Descripción: Generador de analizador léxico
*************************************************************************************/

import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Scanner;

public class Generador_Codigo_Scanner {

    String plantilla_main_path = "/home/martin/NetBeansProjects/Proy_DLP_3/src/Main_Plantilla.txt";
    String plantilla_return_path = "/home/martin/NetBeansProjects/Proy_DLP_3/src/Retorno_Funcion.txt";
    String plantilla_token_path = "/home/martin/NetBeansProjects/Proy_DLP_3/src/Token.txt";
    //--------------------------------------------------------------------------
    //##########################################################################
        HashMap<String,String> Characters_SetDecl_Java = new LinkedHashMap<String,String>();
        HashMap<String,String> Keywords_KeywordDecl = new LinkedHashMap<String,String>();
        HashMap<String,String> Tokens_TokenDecl = new LinkedHashMap<String,String>();
        String nombre_scanner = "";
    //##########################################################################
    //##########################################################################
        String descripcion_error = "";
        boolean error=false;
    //##########################################################################
    LinkedList<String> metodos_scanner = new LinkedList<String>();
    String clase_main = "";
    String clase_retorno_funcion = "";
    int contador_TokenTerms = 0;
    int contador_TokenExpr = 0;
    int contador_TokenFactor = 0;
    public static LinkedList<String> listado_de_tokens = new LinkedList<String>();

    /***********************************************
     * Método: Generador_Codigo
     * Uso: Constructor
    ***********************************************/
    public Generador_Codigo_Scanner(){}

    /***********************************************
     * Método: Generador_Codigo
     * Uso: Constructor
    ***********************************************/
    public Generador_Codigo_Scanner(HashMap<String, String> Characters_SetDecl_Java, HashMap<String, String> Keywords_KeywordDecl, HashMap<String, String> Tokens_TokenDecl, String nombre_scanner) {
        this.Characters_SetDecl_Java = Characters_SetDecl_Java;
        this.Keywords_KeywordDecl = Keywords_KeywordDecl;
        this.Tokens_TokenDecl = Tokens_TokenDecl;
        this.nombre_scanner = nombre_scanner;
        this.Generar_Metodos();
        this.Generar_Clase_Scanner();
        if(this.error==false){
            this.Generar_Clase_Main();
            this.Generar_Clase_RetornoFuncion();
        }
    }

    /***********************************************
     * Método: Guardar_Archivo
     * Uso: guarda texto en un archivo en path/nombre
     * @param nombre contiene el nombre y la extensión del archivo
     * @param pah contiene únicamente el path del archivo
     * @param texto contiene lo que se desea guardar
    ***********************************************/
    public void Guardar_Archivo(String path, String nombre, String texto){
        String archivo = path+"/"+nombre;
        //boolean booleano = new File(archivo).mkdir();

        File selectedFile = new File(archivo);
        try {
            PrintWriter fileOut = new PrintWriter(new FileWriter(selectedFile));
            fileOut.print(texto);
            fileOut.close();
        }catch (Exception ex){
            Main.Print("No se pudo guardar el archivo: "+archivo);
        }
    }

    /***********************************************
     * Método: error
     * Uso: Se llama cuando hay un error y activa una bandera
     * @param descripcion contiene la descripción del error
    ***********************************************/
    public void error(String descripcion){
        Main.Print("\n+++---+++---+++---+++---+++---+++---+++---+++---+++---+++\n");
        Main.Print("Descripción: "+descripcion);
        Main.Print("\n+++---+++---+++---+++---+++---+++---+++---+++---+++---+++\n");
        this.error=true;
    }

    /***********************************************
     * Método: Generar_Metodos
     * Uso: Guarda en la lista de métodos los métodos
     *      que va generando
    ***********************************************/
    public void Generar_Metodos() {
        this.Generar_Metodos_Generales();
        this.Generar_Metodos_Characters_KeyWords();
        this.Generar_Metodos_Tokens();
        this.Generar_Constructor();
    }

    /***********************************************
     * Método: Generar_Metodos_Generales
     * Uso: Genera los métodos de uso general..
     *      como expect, complementar_cadena...
    ***********************************************/
    public void Generar_Metodos_Generales() {
        String Scan = (""+
            "\t"+"/***********************************************"+"\n"+
            "\t"+"* Método: Scan"+"\n"+
            "\t"+"* Uso: Retorna el primer token de la lista y lo saca"+"\n"+
            "\t"+"* @return Token"+"\n"+
            "\t"+"***********************************************/"+"\n"+
            "\t"+"public Token Scan(){"+"\n"+
            "\t"+"	try{"+"\n"+
            "\t"+"		return this.tokens_encontrados.pop();"+"\n"+
            "\t"+"	}catch(Exception exp){"+"\n"+
            "\t"+"		return (new Token(-1,\"EOF\",\"\"));"+"\n"+
            "\t"+"	}"+"\n"+
            "\t"+"}"+"\n"+
         "");
        String expect = (""+
            "\t"+"/***********************************************"+"\n"+
            "\t"+"* Método: expect"+"\n"+
            "\t"+"* Uso: Revisa si lo ingresado hace match con"+"\n"+
            "\t"+"*      el patrón dado..."+"\n"+
            "\t"+"* @param regex contiene la regex con la que hay que evaluar"+"\n"+
            "\t"+"* @param cadena que hay que revisar que haga match"+"\n"+
            "\t"+"* @return Retorno_Funcion"+"\n"+
            "\t"+"***********************************************/"+"\n"+
            "\t"+"public Retorno_Funcion expect(int[] regex, String cadena) {"+"\n"+
            "\t"+"	for(int i=0;i<regex.length;i++){"+"\n"+
            "\t"+"		try{"+"\n"+
            "\t"+"			if(regex[i]!=(int)cadena.charAt(i)){"+"\n"+
            "\t"+"				return new Retorno_Funcion();"+"\n"+
            "\t"+"			}"+"\n"+
            "\t"+"		}catch(Exception exp){"+"\n"+
            "\t"+"			return new Retorno_Funcion();"+"\n"+
            "\t"+"		}"+"\n"+
            "\t"+"	}"+"\n"+
            "\t"+"	Retorno_Funcion ret = new Retorno_Funcion();"+"\n"+
            "\t"+"	ret.indice = regex.length;"+"\n"+
            "\t"+"	ret.cadena = cadena.substring(0,regex.length);"+"\n"+
            "\t"+"	ret.aceptado = true;"+"\n"+
            "\t"+"	return ret;"+"\n"+
            "\t"+"}"+"\n"+
         "");


        String Complementar_cadena = (""+
            "\t"+"/***********************************************"+"\n"+
            "\t"+"* Método: Complementar_cadena"+"\n"+
            "\t"+"* Uso: Corta la cadena hasta el índice i"+"\n"+
            "\t"+"* @param a contiene el índice hasta donde cortar"+"\n"+
            "\t"+"* @param cadena contiene la cadena a cortar"+"\n"+
            "\t"+"***********************************************/"+"\n"+
            "\t"+"public String Complementar_cadena(String cadena, int a){"+"\n"+
            "\t"+"	try{"+"\n"+
            "\t"+"		String cadena2 = \"\";"+"\n"+
            "\t"+"		cadena2 = cadena.substring(a);"+"\n"+
            "\t"+"		//System.out.println(\"Cadena cortada: \"+cadena2);"+"\n"+
            "\t"+"		return cadena2;"+"\n"+
            "\t"+"	}catch(Exception exp){"+"\n"+
            "\t"+"		System.out.println(\"Error al copiar cortar la cadena: \"+cadena+\" en el índice: \"+a);"+"\n"+
            "\t"+"	}"+"\n"+
            "\t"+"	return \"\";"+"\n"+
            "\t"+"}"+"\n"+
        "");

        //agrega Scan a la lista de métodos
        this.metodos_scanner.add(Scan);
        //agrega expect a la lista de métodos
        this.metodos_scanner.add(expect);
        //agrega Complementar_cadena a la lista de métodos
        this.metodos_scanner.add(Complementar_cadena);

        //Main.Print(expect);
        //Main.Print(Complementar_cadena);
        //this.Guardar_Archivo(Main.path_to_save, "Metodos_Generales.java", expect+"\n\n\n"+Complementar_cadena);

    }

    /***********************************************
     * Método: Generar_Metodos_Characters_KeyWords
     * Uso: Genera los métodos a partir de los hashMaps
     *      de Characters y Keywords
    ***********************************************/
    public void Generar_Metodos_Characters_KeyWords() {

        Iterator iterator = this.Characters_SetDecl_Java.keySet().iterator();

        while( iterator. hasNext() ){
            String nombre = (String) iterator.next();
            String regex = (String) this.Characters_SetDecl_Java.get(nombre);
            Main.PrintDB("#) "+nombre+" = "+regex);
            String retorno = (
                    "\t"+"/***********************************************"+"\n"+
                    "\t"+"* Método: "+DefCocol.Revisar_Palabras_Reservadas(nombre)+""+"\n"+
                    "\t"+"* Uso: Revisa si lo ingresado hace match con"+"\n"+
                    "\t"+"*      toda la sintaxis de "+nombre+""+"\n"+
                    "\t"+"* @param cadena"+"\n"+
                    "\t"+"* @return Retorno_Funcion"+"\n"+
                    "\t"+"***********************************************/"+"\n"+
                    "\t"+"public Retorno_Funcion "+DefCocol.Revisar_Palabras_Reservadas(nombre)+"(String cadena) {"+"\n"+
                    "\t"+"	// "+nombre+" = "+regex+""+"\n"+
                    "\t"+"	//------------------------------------------"+"\n"+
                    "\t"+"	int[] regex = "+regex+";"+"\n"+
                    "\t"+"	LinkedList<Integer> lista = new LinkedList<Integer>();"+"\n"+
                    "\t"+"	Retorno_Funcion ret = new Retorno_Funcion();"+"\n"+
                    "\t"+"	for(int a : regex){"+"\n"+
                    "\t"+"		lista.add(a);"+"\n"+
                    "\t"+"	}"+"\n"+
                    "\t"+"	if(cadena.isEmpty()==true){"+"\n"+
                    "\t"+"		return new Retorno_Funcion();"+"\n"+
                    "\t"+"	}"+"\n"+
                    "\t"+"	if(lista.contains((int)cadena.charAt(0))==true){"+"\n"+
                    "\t"+"		ret.aceptado=true;"+"\n"+
                    "\t"+"		ret.indice=1;"+"\n"+
                    "\t"+"		ret.cadena=\"\"+cadena.charAt(0);"+"\n"+
                    "\t"+"	}"+"\n"+
                    "\t"+"	return ret;"+"\n"+
                    "\t"+"}"+"\n"
            );
            this.metodos_scanner.add(retorno);
        }
        
        Main.PrintDB("\nKeyWords:");

        iterator = this.Keywords_KeywordDecl.keySet().iterator();
        while( iterator. hasNext() ){
            String nombre = (String) iterator.next();
            String regex = (String) this.Keywords_KeywordDecl.get(nombre);
            regex = regex.substring(1,regex.length()-1);//para quitarles las comillas... \" {ANY} \"
            LinkedList<Integer> lista = new LinkedList<Integer>();
            for(int a : regex.toCharArray()){
                lista.add(a);
            }
            Main.PrintDB("acá tengo que ver: "+lista.toString());
            String retorno = (
                    "\t"+"/***********************************************"+"\n"+
                    "\t"+"* Método: "+DefCocol.Revisar_Palabras_Reservadas(nombre)+""+"\n"+
                    "\t"+"* Uso: Revisa si lo ingresado hace match con"+"\n"+
                    "\t"+"*      toda la sintaxis de "+nombre+""+"\n"+
                    "\t"+"* @param cadena"+"\n"+
                    "\t"+"* @return Retorno_Funcion"+"\n"+
                    "\t"+"***********************************************/"+"\n"+
                    "\t"+"public Retorno_Funcion "+DefCocol.Revisar_Palabras_Reservadas(nombre)+"(String cadena) {"+"\n"+
                    "\t"+"	// "+nombre+" = "+regex+""+"\n"+
                    "\t"+"	//------------------------------------------"+"\n"+
                    "\t"+"	int[] regex = {"+lista.toString().substring(1,lista.toString().length()-1)+"};"+"\n"+
                    "\t"+"	Retorno_Funcion ret = this.expect(regex,cadena);"+"\n"+
                    "\t"+"	return ret;"+"\n"+
                    "\t"+"}"+"\n"
            );

            Main.PrintDB("#) "+nombre+" = "+regex);
            this.metodos_scanner.add(retorno);


        }
    }

    public void Generar_Constructor() {

        String tokens = "";
        int contador = 0;
        Iterator iterator = this.Keywords_KeywordDecl.keySet().iterator();
        while( iterator. hasNext() ){
            String nombre = (String) iterator.next();
            String nombre2 = nombre;
            if(nombre.endsWith("_0")){
                nombre= nombre.substring(0, nombre.length()-2);
            }
            tokens+="\t"+"	tokens_posibles.add(\""+nombre+"\"); //"+this.Keywords_KeywordDecl.get(nombre2)+"\n";
        }
        iterator = this.Tokens_TokenDecl.keySet().iterator();
        while( iterator. hasNext() ){
            String nombre = (String) iterator.next();
            if(nombre.endsWith("_0")){
                nombre= nombre.substring(0, nombre.length()-2);
            }
            tokens+="\t"+"	tokens_posibles.add(\""+nombre+"\"); //"+this.Tokens_TokenDecl.get(nombre)+"\n";
        }
        
        String constructor = (
                "\t"+"/***********************************************"+"\n"+
                "\t"+"* Método: "+Main.nombre_scanner+""+"\n"+
                "\t"+"* Uso: Constructor"+"\n"+
                "\t"+"* @param cadena a evaluar"+"\n"+
                "\t"+"***********************************************/"+"\n"+
                "\t"+"public "+Main.nombre_scanner+"(String cadena) {"+"\n"+
                "\t"+"	//------------------------------------------"+"\n"+
                ""+tokens+"\n"+
                "\t"+"	//------------------------------------------"+"\n"+
                "\t"+"	System.out.println(\"-----------------------------------\\n\");"+"\n"+
                "\t"+"	System.out.println(\"Cadena a revisar: \\n\"+cadena);"+"\n"+
                "\t"+"	System.out.println(\"-----------------------------------\\n\");"+"\n"+
                "\t"+"	//------------------------------------------"+"\n"+
                "\t"+"	String cadena1 = cadena;"+"\n"+
                "\t"+"	"+"\n"+
                "\t"+"	Retorno_Funcion ret = new Retorno_Funcion();"+"\n"+
                "\t"+"	do{"+"\n"+
                "\t"+"		ret = this.Opciones_Token(cadena1);"+"\n"+
                "\t"+"		cadena1 = this.Complementar_cadena(cadena1, ret.indice);"+"\n"+
                "\t"+"		Retorno_Funcion retA = this.Opciones_Token(cadena1);"+"\n"+
                "\t"+"		if(retA.aceptado==false){"+"\n"+
                "\t"+"			//System.out.println(\"si se metio 1\");"+"\n"+
                "\t"+"			Pattern pattern = Pattern.compile(\"(\\\\s)+\");"+"\n"+
                "\t"+"			Matcher matcher = pattern.matcher(cadena1);"+"\n"+
                "\t"+"			if (matcher.find()) {"+"\n"+
                "\t"+"			    if(matcher.start()==0){"+"\n"+
                "\t"+"				//System.out.println(\"si se metio 2\");"+"\n"+
                "\t"+"				cadena1 = this.Complementar_cadena(cadena1, matcher.end());"+"\n"+
                "\t"+"		    	}"+"\n"+
                "\t"+"			}"+"\n"+
                "\t"+"		}"+"\n"+
                "\t"+"		if(ret.aceptado==true){"+"\n"+
                "\t"+"			//System.out.println(\"Token encontrado: \"+ret.token+\" con la cadena: \"+ret.cadena);"+"\n"+
                "\t"+"			int indice = this.tokens_posibles.indexOf(ret.token);"+"\n"+
                "\t"+"			tokens_encontrados.add(new Token(indice,this.tokens_posibles.get(indice),ret.cadena));"+"\n"+
                "\t"+"			todos_los_tokens.add(new Token(indice,this.tokens_posibles.get(indice),ret.cadena));"+"\n"+
                "\t"+"		}"+"\n"+
                "\t"+"		else{"+"\n"+
                "\t"+"			break;"+"\n"+
                "\t"+"		}"+"\n"+
                "\t"+"	}while(true);"+"\n"+
                "\t"+"	if(cadena1.isEmpty()==false){"+"\n"+
                "\t"+"		tokens_encontrados.add(new Token(-1,\"EOF\",cadena1));"+"\n"+
                "\t"+"		todos_los_tokens.add(new Token(-1,\"EOF\",cadena1));"+"\n"+
                "\t"+"		System.out.println(\"No se hizo match con ningún token en la siguiente cadena: \"+cadena1);"+"\n"+
                "\t"+"	}"+"\n"+
                "\t"+"}"+
        "");
       Constructor_TokenExpr();
       Constructor_KeyWords();
       this.metodos_scanner.addFirst(constructor);
    }

    public void Constructor_TokenExpr(){
        
        String metodo = (
                "\t"+"/***********************************************"+"\n"+
                "\t"+"* Método: Opciones_Token"+"\n"+
                "\t"+"* Uso: Verifica si lo ingresado es alguna de las opciones de token"+"\n"+
                "\t"+"* @param cadena a evaluar"+"\n"+
                "\t"+"***********************************************/"+"\n"+
                "\t"+"public Retorno_Funcion Opciones_Token(String cadena) {"+"\n"+
                "\t"+"	//------------------------------------------"+"\n"+
        "");
        
        LinkedList<String> TokenDecl_List = new LinkedList<String>();
        LinkedList<String> TokenDecl_Token = new LinkedList<String>();
        
        Iterator iterator = this.Tokens_TokenDecl.keySet().iterator();
        while( iterator. hasNext() ){
            String nombre = (String) iterator.next();
            String regex = (String) this.Tokens_TokenDecl.get(nombre);
            TokenDecl_List.add(regex);
            TokenDecl_Token.add(nombre);
        }
        
        
        for(String a : TokenDecl_Token){
            Main.PrintDB("-> "+a);
        }
        
        //metodo+=(""+"\n"+"\t"+"	Retorno_Funcion ret = new Retorno_Funcion();"+"\n");
        metodo+=(""+"\n"+"\t"+"	LinkedList<Retorno_Funcion> lista_ret = new LinkedList<Retorno_Funcion>();"+"\n");

        for(int i=0;i<TokenDecl_List.size();i++){
            String cadenita = TokenDecl_List.get(i);
            String token = TokenDecl_Token.get(i);
            String nombre_token = token;
            if(nombre_token.endsWith("_0")){
                nombre_token = nombre_token.substring(0, nombre_token.length()-2);
            }
            if(cadenita.endsWith(" EXCEPT KEYWORDS")==true){
                String cadena1 = cadenita.substring(0,cadenita.length()-16);
                metodo+=("" +"\n"+
                    "\t"+"	//------------------------------------------"+"\n"+
                    "\t"+"	// Revisa: "+cadenita+"\n"+
                    "\t"+"	Retorno_Funcion ret"+i+" = this."+DefCocol.Revisar_Palabras_Reservadas(token)+"(cadena);"+"\n"+
                    "\t"+"	if(ret"+i+".aceptado==true){"+"\n"+
                    "\t"+"		Retorno_Funcion ret_"+i+" = this.Opciones_KeyWords(ret"+i+".cadena);"+"\n"+
                    "\t"+"		if(ret_"+i+".aceptado==true && ret"+i+".cadena.compareTo(ret_"+i+".cadena)==0){"+"\n"+
                    "\t"+"			ret"+i+".token = ret_"+i+".token;"+"\n"+
                    "\t"+"		}"+"\n"+
                    "\t"+"		else{"+"\n"+
                    "\t"+"			ret"+i+".token = \""+nombre_token+"\";"+"\n"+
                    "\t"+"		}"+"\n"+
                    "\t"+"		lista_ret.add(ret"+i+");"+"\n"+
                    "\t"+"	}"+"\n"+
                    "\t"+"	//------------------------------------------"+"\n"+
                "");
            }
            else{
                metodo+=("" +"\n"+
                    "\t"+"	//------------------------------------------"+"\n"+
                    "\t"+"	// Revisa: "+cadenita+"\n"+
                    "\t"+"	Retorno_Funcion ret"+i+" = this."+DefCocol.Revisar_Palabras_Reservadas(token)+"(cadena);"+"\n"+
                    "\t"+"	if(ret"+i+".aceptado==true){"+"\n"+
                    "\t"+"		ret"+i+".token = \""+nombre_token+"\";"+"\n"+
                    "\t"+"		lista_ret.add(ret"+i+");"+"\n"+
                    "\t"+"	}"+"\n"+
                    "\t"+"	//------------------------------------------"+"\n"+
                "");
            }
        }
        
        metodo+=("" +"\n"+
                "\t"+"	if(lista_ret.size()==0){"+"\n"+
                "\t"+"		return (new Retorno_Funcion());"+"\n"+
                "\t"+"	}"+"\n"+
                "\t"+"	Collections.sort(lista_ret, new Comparator<Retorno_Funcion>() {"+"\n"+
                "\t"+"		public int compare(Retorno_Funcion o1, Retorno_Funcion o2) {"+"\n"+
                "\t"+"			Integer a1 = o1.cadena.length();"+"\n"+
                "\t"+"			Integer a2 = o2.cadena.length();"+"\n"+
                "\t"+"			return a2-a1;"+"\n"+
                "\t"+"		}"+"\n"+
                "\t"+"	});"+"\n"+
                "\t"+"	return lista_ret.getFirst();"+"\n"+
        "");
        metodo+="\t"+"}";
        this.metodos_scanner.addFirst(metodo);
    }

    public void Constructor_KeyWords(){

        String metodo = (
                "\t"+"/***********************************************"+"\n"+
                "\t"+"* Método: Opciones_KeyWords"+"\n"+
                "\t"+"* Uso: Revisa si es algún keyword"+"\n"+
                "\t"+"* @param cadena a evaluar"+"\n"+
                "\t"+"***********************************************/"+"\n"+
                "\t"+"public Retorno_Funcion Opciones_KeyWords(String cadena) {"+"\n"+
                "\t"+"	//------------------------------------------"+"\n"+
        "");

        LinkedList<String> TokenDecl_List = new LinkedList<String>();
        LinkedList<String> TokenDecl_Token = new LinkedList<String>();

        Iterator iterator = this.Keywords_KeywordDecl.keySet().iterator();
        while( iterator. hasNext() ){
            String nombre = (String) iterator.next();
            if(nombre.endsWith("_0")){
                nombre= nombre.substring(0, nombre.length()-2);
            }
            String regex = (String) this.Keywords_KeywordDecl.get(nombre);
            TokenDecl_List.add(regex);
            TokenDecl_Token.add(nombre);
        }


        for(String a : TokenDecl_Token){
            Main.PrintDB("-> "+a);
        }

        //metodo+=(""+"\n"+"\t"+"	Retorno_Funcion ret = new Retorno_Funcion();"+"\n");
        metodo+=(""+"\n"+"\t"+"	LinkedList<Retorno_Funcion> lista_ret = new LinkedList<Retorno_Funcion>();"+"\n");

        for(int i=0;i<TokenDecl_List.size();i++){
            String cadenita = TokenDecl_List.get(i);
            String token = TokenDecl_Token.get(i);
            metodo+=("" +"\n"+
                "\t"+"	//------------------------------------------"+"\n"+
                "\t"+"	// Revisa: "+cadenita+"\n"+
                "\t"+"	Retorno_Funcion ret"+i+" = this."+DefCocol.Revisar_Palabras_Reservadas(token)+"(cadena);"+"\n"+
                "\t"+"	if(ret"+i+".aceptado==true){"+"\n"+
                "\t"+"		ret"+i+".token = \""+token+"\";"+"\n"+
                "\t"+"		lista_ret.add(ret"+i+");"+"\n"+
                "\t"+"	}"+"\n"+
                "\t"+"	//------------------------------------------"+"\n"+
            "");
        }

        metodo+=("" +"\n"+
                "\t"+"	if(lista_ret.size()==0){"+"\n"+
                "\t"+"		return (new Retorno_Funcion());"+"\n"+
                "\t"+"	}"+"\n"+
                "\t"+"	Collections.sort(lista_ret, new Comparator<Retorno_Funcion>() {"+"\n"+
                "\t"+"		public int compare(Retorno_Funcion o1, Retorno_Funcion o2) {"+"\n"+
                "\t"+"			Integer a1 = o1.cadena.length();"+"\n"+
                "\t"+"			Integer a2 = o2.cadena.length();"+"\n"+
                "\t"+"			return a2-a1;"+"\n"+
                "\t"+"		}"+"\n"+
                "\t"+"	});"+"\n"+
                "\t"+"	return lista_ret.getFirst();"+"\n"+
        "");
        metodo+="\t"+"}";
        this.metodos_scanner.addFirst(metodo);
    }

    /***********************************************
     * Método: Generar_Clase_Scanner
     * Uso: Genera la clase Scanner requerido
    ***********************************************/
    public void Generar_Clase_Scanner() {

        String scanner_total = (
            "/*************************************************************************************"+"\n"+
            " * Nombre del archivo: "+Main.nombre_scanner+".java"+"\n"+
            " * Universidad del Valle de Guatemala"+"\n"+
            " * Curso: Diseño de Lenguajes de Programación"+"\n"+
            " * @author martin"+"\n"+
            " *          Martín Guzmán 08041"+"\n"+
            " * Fecha: Abril de 2010"+"\n"+
            " * Descripción: Segundo proyecto. Clase que contiene el Scanner" +"\n"+
            " *          generado para el archivo de entrada"+"\n"+
            "*************************************************************************************/"+"\n"+
            ""+"\n"+
            "import java.io.BufferedReader;"+"\n"+
            "import java.io.File;"+"\n"+
            "import java.io.FileOutputStream;"+"\n"+
            "import java.io.FileWriter;"+"\n"+
            "import java.io.PrintWriter;"+"\n"+
            "import java.io.FileNotFoundException;"+"\n"+
            "import java.util.Scanner;"+"\n"+
            "import java.util.LinkedList;"+"\n"+
            "import java.util.regex.Matcher;"+"\n"+
            "import java.util.regex.Pattern;"+"\n"+
            "import javax.swing.JFileChooser;"+"\n"+
            "import java.util.Collections;"+"\n"+
            "import java.util.Comparator;"+"\n"+
            "import java.util.LinkedList;"+"\n"+
            "import java.util.List;"+"\n"+
            "import java.util.regex.Matcher;"+"\n"+
            "import java.util.regex.Pattern;"+"\n"+
            "import java.util.HashMap;"+"\n"+
            "import java.util.Iterator;"+"\n"+
            "import java.util.LinkedHashMap;"+"\n"+
            "import java.util.Scanner;"+"\n"+
            "import java.util.logging.Level;"+"\n"+
            "import java.util.logging.Logger;"+"\n"+
            ""+"\n"+
            "public class "+Main.nombre_scanner+" {"+"\n"+
            ""+"\n"+
            "\tpublic LinkedList<String> tokens_posibles = new LinkedList<String>();"+"\n"+
            "\tpublic LinkedList<Token> tokens_encontrados = new LinkedList<Token>();"+"\n"+
            "\tpublic LinkedList<Token> todos_los_tokens = new LinkedList<Token>();"+"\n"+
            ""+"\n"
        );
        
        for(int i=0;i<this.metodos_scanner.size();i++){
            scanner_total+="\n"+
                    this.metodos_scanner.get(i)
                    +"\n";
        }
        
        scanner_total+="\n"+"}";

        if(this.error==false){
            this.Guardar_Archivo(Main.path_to_save, Main.nombre_scanner+".java", scanner_total);
        }
    }

    /***********************************************
     * Método: Generar_Clase_Main
     * Uso: Jala la plantilla para generar la clase Main
    ***********************************************/
    public void Generar_Clase_Main() {

        String cadena_arte_total = "";
        
        File file;
        file = new File(plantilla_main_path);
        Scanner scan_file;
        try {
            scan_file = new Scanner(file);
             while(scan_file.hasNext()){
                this.clase_main+=(scan_file.nextLine())+"\n";
            }
        } catch (Exception ex) {
            Main.Print("\tLa plantilla del Main no se pudo abrir");
        }

        String[] lineas = new String[4];
        lineas[0]="";
        lineas[1]="";
        lineas[2]="";
        lineas[3]="";
        
        for(int i=0;i<this.nombre_scanner.length();i++){
            char caracter = this.nombre_scanner.charAt(i);
            lineas[0]+=" ____ ";
            lineas[1]+="||"+caracter+" ||";
            lineas[2]+="||__||";
            lineas[3]+="|/__\\\\\\\\|";
        }
        
        Main.PrintDB(lineas[0]);
        Main.PrintDB(lineas[1]);
        Main.PrintDB(lineas[2]);
        Main.PrintDB(lineas[3]);
        cadena_arte_total ="System.out.println(\""+lineas[0]+"\");\n";
        cadena_arte_total +="            System.out.println(\""+lineas[1]+"\");\n";
        cadena_arte_total +="            System.out.println(\""+lineas[2]+"\");\n";
        cadena_arte_total +="            System.out.println(\""+lineas[3]+"\");\n";
        
        this.clase_main = this.clase_main.replaceAll("PLANTILLA1", cadena_arte_total);
        this.clase_main = this.clase_main.replaceAll("PLANTILLA2", Main.nombre_scanner);
        this.Guardar_Archivo(Main.path_to_save, "Main.java", this.clase_main);

    }

    /***********************************************
     * Método: Generar_Clase_RetornoFuncion
     * Uso: Jala la plantilla para generar la clase Retorno Funcion
    ***********************************************/
    public void Generar_Clase_RetornoFuncion() {
        File file;
        file = new File(this.plantilla_return_path);
        Scanner scan_file;
        try {
            scan_file = new Scanner(file);
             while(scan_file.hasNext()){
                this.clase_retorno_funcion+=(scan_file.nextLine())+"\n";
            }
        } catch (Exception ex) {
            Main.Print("\tLa plantilla del Retorno_Funcion no se pudo abrir");
        }

        this.Guardar_Archivo(Main.path_to_save, "Retorno_Funcion.java", this.clase_retorno_funcion);

        String token = "";
        file = new File(this.plantilla_token_path);
        try {
            scan_file = new Scanner(file);
             while(scan_file.hasNext()){
                token+=(scan_file.nextLine())+"\n";
            }
        } catch (Exception ex) {
            Main.Print("\tLa plantilla del token no se pudo abrir");
        }

        this.Guardar_Archivo(Main.path_to_save, "Token.java", token);
    }

    /***********************************************
     * Método: Generar_Metodos_Tokens
     * Uso: Manda a crear un método por cada token
    ***********************************************/
    public void Generar_Metodos_Tokens() {

        Iterator iterator = this.Tokens_TokenDecl.keySet().iterator();

        while( iterator. hasNext() ){
            String nombre = (String) iterator.next();
            String regex = (String) this.Tokens_TokenDecl.get(nombre);
            Main.PrintDB("#) "+nombre+" = "+regex);
            if(regex.endsWith(" EXCEPT KEYWORDS")==true){
                regex = regex.substring(0, regex.length()-16);
            }
            Generar_Metodo_TokenExpr(nombre,regex);
        }
    }

    /***********************************************
     * Método: Obtener_Lista_TokenTerm
     * Uso: Manda a crear un método por cada token
     * @param regex contiene a donde sacar la lista
     * @return LinkedList<String> con los TokenFactor
    ***********************************************/
    public LinkedList<String> Obtener_Lista_TokenTerm(String regex) {

        LinkedList<String> lista_retorno = new LinkedList<String>();
        String cadena = regex;

        Retorno_Funcion ret1 = DefCocol.TokenTerm(cadena);
        if(ret1.aceptado==true){
            cadena = DefCocol.Complementar_cadena(cadena, ret1.indice);
            lista_retorno.add(ret1.cadena);
        }

        while(true){
            //revisar si hay otro tokenTerm
            //{'|' TokenTerm}
            Retorno_Funcion ret2 = DefCocol.expect(DefCocol.space+"\\|"+DefCocol.space, cadena);
            if(ret2.aceptado==false){
                break;
            }
            cadena = DefCocol.Complementar_cadena(cadena, ret2.indice);

            Retorno_Funcion ret22 = DefCocol.TokenTerm(cadena);
            if(ret22.aceptado==true){
                cadena = DefCocol.Complementar_cadena(cadena, ret22.indice);
                lista_retorno.add(ret22.cadena);
            }
            else{
                Main.Print("Acá nunca debería de llegar...");
                break;
            }
        }

        return lista_retorno;
    }

    /***********************************************
     * Método: Obtener_Lista_TokenFactor
     * Uso: Manda a crear un método por cada token
     * @param regex contiene a donde sacar la lista
     * @return LinkedList<String> con los TokenFactor
    ***********************************************/
    public LinkedList<String> Obtener_Lista_TokenFactor(String regex) {

        LinkedList<String> lista_retorno = new LinkedList<String>();
        String cadena = regex;

        Retorno_Funcion ret1 = DefCocol.TokenFactor(cadena);
        if(ret1.aceptado==true){
            cadena = DefCocol.Complementar_cadena(cadena, ret1.indice);
            lista_retorno.add(ret1.cadena);
        }

        while(true){
            //revisar si hay otro tokenTerm
            //{TokenFactor}
            Retorno_Funcion ret22 = DefCocol.TokenFactor(cadena);
            if(ret22.aceptado==true){
                cadena = DefCocol.Complementar_cadena(cadena, ret22.indice);
                lista_retorno.add(ret22.cadena);
            }
            else{
                break;
            }
        }
        return lista_retorno;
    }

    /***********************************************
     * Método: Generar_Metodos_Tokens
     * Uso: Manda a crear un método por cada token
    ***********************************************/
    public void Generar_Metodo_TokenExpr(String nombre, String regex) {
        Main.PrintDB("\tNombre: "+nombre);
        Main.PrintDB("\tRegex: ."+regex+".");

        String metodo = ("" +
                "\t"+"/***********************************************"+"\n"+
                "\t"+"* Método: "+nombre+""+"\n"+
                "\t"+"* Uso: Revisa si lo ingresado hace match con"+"\n"+
                "\t"+"*      toda la sintaxis de "+nombre+""+"\n"+
                "\t"+"* @param cadena"+"\n"+
                "\t"+"* @return Retorno_Funcion"+"\n"+
                "\t"+"***********************************************/"+"\n"+
                "\t"+"public Retorno_Funcion "+nombre+"(String cadena) {"+"\n"+
                "\t"+"	//------------------------------------------"+"\n"+
                "\t"+"	// TokenExpr:  "+nombre+" = "+regex+""+"\n"+
                "\t"+"	//------------------------------------------"+"\n"+
        "");

        LinkedList<String> TokenTerms = Obtener_Lista_TokenTerm(regex);

        for(String a : TokenTerms){
            Main.PrintDB("-> "+a);
        }

        metodo+=(""+"\n"+"\t"+"	Retorno_Funcion ret = new Retorno_Funcion();"+"\n");
        metodo+=(""+"\n"+"\t"+"	LinkedList<String> lista_ret = new LinkedList<String>();"+"\n");

        for(int i=0;i<TokenTerms.size();i++){
            String cadenita = TokenTerms.get(i);
            metodo+=("" +"\n"+
                "\t"+"	//------------------------------------------"+"\n"+
                "\t"+"	// Revisa: "+cadenita+" en FuncionTokenTerm"+this.contador_TokenTerms+"\n"+
                "\t"+"	Retorno_Funcion ret"+this.contador_TokenTerms+" = this.FuncionTokenTerm"+this.contador_TokenTerms+"(cadena);"+"\n"+
                "\t"+"	if(ret"+this.contador_TokenTerms+".aceptado==true){"+"\n"+
                "\t"+"		lista_ret.add(ret"+this.contador_TokenTerms+".cadena);"+"\n"+
                "\t"+"	}"+"\n"+
                "\t"+"	//------------------------------------------"+"\n"+
            "");
            this.Generar_Metodo_TokenTerm("FuncionTokenTerm"+this.contador_TokenTerms++, cadenita);
        }
        
        metodo+=("" +
                "\t"+"	if(lista_ret.size()==0){"+"\n"+
                "\t"+"		return (new Retorno_Funcion());"+"\n"+
                "\t"+"	}"+"\n"+
                "\t"+"	Collections.sort(lista_ret, new Comparator<String>() {"+"\n"+
                "\t"+"		public int compare(String o1, String o2) {"+"\n"+
                "\t"+"			Integer a1 = o1.length();"+"\n"+
                "\t"+"			Integer a2 = o2.length();"+"\n"+
                "\t"+"			return a2-a1;"+"\n"+
                "\t"+"		}"+"\n"+
                "\t"+"	});"+"\n"+
                "\t"+"	//System.out.println(lista_ret.toString());"+"\n"+
                "\t"+"	ret.aceptado=true;"+"\n"+
                "\t"+"	ret.indice=lista_ret.getFirst().length();"+"\n"+
                "\t"+"	ret.cadena=lista_ret.getFirst();"+"\n"+
                "\t"+"	return ret;"+"\n"+
                "");

        metodo+="\n\t"+"}";

        this.metodos_scanner.add(metodo);
    }

    /***********************************************
     * Método: Generar_Metodos_TokenTerm
     * Uso: Manda a crear un método por cada token
    ***********************************************/
    public void Generar_Metodo_TokenTerm(String nombre, String regex) {
        Main.PrintDB("\tNombre TokenTerm: "+nombre);
        Main.PrintDB("\tRegex TokenTerm: ."+regex+".");

        String metodo = ("" +
                "\t"+"/***********************************************"+"\n"+
                "\t"+"* Método: "+nombre+""+"\n"+
                "\t"+"* Uso: Revisa si lo ingresado hace match con"+"\n"+
                "\t"+"*      toda la sintaxis de "+nombre+""+"\n"+
                "\t"+"* @param cadena"+"\n"+
                "\t"+"* @return Retorno_Funcion"+"\n"+
                "\t"+"***********************************************/"+"\n"+
                "\t"+"public Retorno_Funcion "+nombre+"(String entrada) {"+"\n"+
                "\t"+"	//------------------------------------------"+"\n"+
                "\t"+"	// TokenTerm: "+nombre+" = "+regex+""+"\n"+
                "\t"+"	//------------------------------------------"+"\n"+
                "\t"+"	String cadenaA = entrada;"+"\n"+
                "\t"+"	Retorno_Funcion ret = new Retorno_Funcion();"+"\n"+
        "");

        LinkedList<String> TokenFactors = Obtener_Lista_TokenFactor(regex);

        for(String a : TokenFactors){
            Main.PrintDB("TokenFactors -> "+a);
        }
        int contador=0;
        for(int i=0;i<TokenFactors.size();i++){
            String cadenita = TokenFactors.get(i);
            metodo+=this.Codigo_para_TokenFactor(cadenita,contador);
            contador++;
        }

        for(int i=0;i<contador;i++){
            metodo+=("\t"+"	ret.indice+=ret"+i+".indice;"+"\n");
            metodo+=("\t"+"	ret.cadena+=ret"+i+".cadena;"+"\n");
        }

        metodo+=("" +
                "\t"+"	ret.aceptado=true;"+"\n"+
                "\t"+"	return ret;"+"\n"+
                "");
        metodo+="\n\t"+"}";

        this.metodos_scanner.add(metodo);
    }

    public String Codigo_para_TokenFactor(String cadenita, int contador) {

        Retorno_Funcion ret1 = DefCocol.Symbol(cadenita);
        String metodo="";
        if(ret1.aceptado==true){
            Main.PrintDB("Hay un Symbol");
            //si es Symbol hay 3 opciones: que sea string | char | ident
            //ident ------------------------------------------------------------
            Retorno_Funcion ret11 = DefCocol.expect(DefCocol.ident, cadenita);
            if(ret11.aceptado==true){
                String a = DefCocol.Revisar_Palabras_Reservadas(ret11.cadena);
                //revisar si existe el identificador
                if(this.Characters_SetDecl_Java.containsKey(a)==false && this.Tokens_TokenDecl.containsKey(a)==false){
                    this.error("Error. Ident no encontrado: "+a);
                }
                metodo=("" +"\n"+
                "\t"+"	//------------------------------------------"+"\n"+
                "\t"+"	// "+a+" es un ident"+"\n"+
                "\t"+"	Retorno_Funcion ret"+contador+" = this."+a+"(cadenaA);"+"\n"+
                "\t"+"	if(ret"+contador+".aceptado==false){"+"\n"+
                "\t"+"		return new Retorno_Funcion();"+"\n"+
                "\t"+"	}"+"\n"+
                "\t"+"	cadenaA = Complementar_cadena(cadenaA, ret"+contador+".indice);"+"\n"+
                "\t"+"	//------------------------------------------"+"\n"+
                "");
                return metodo;
            }//-----------------------------------------------------------------
            //string -----------------------------------------------------------
            Retorno_Funcion ret12 = DefCocol.expect(DefCocol.string, cadenita);
            if(ret12.aceptado==true){
                LinkedList<Integer> lista = new LinkedList<Integer>();
                for(int a : ret12.cadena.substring(1, ret12.cadena.length()-1).toCharArray()){
                    lista.add(a);
                }
                String cadena = "{"+lista.toString().substring(1, lista.toString().length()-1)+"}";
                metodo=("" +"\n"+
                "\t"+"	//------------------------------------------"+"\n"+
                "\t"+"	// "+ret12.cadena+" es un string"+"\n"+
                "\t"+"	int[] regex"+contador+" = "+cadena+";"+"\n"+
                "\t"+"	Retorno_Funcion ret"+contador+" = this.expect(regex"+contador+",cadenaA);"+"\n"+
                "\t"+"	if(ret"+contador+".aceptado==false){"+"\n"+
                "\t"+"		return new Retorno_Funcion();"+"\n"+
                "\t"+"	}"+"\n"+
                "\t"+"	cadenaA = Complementar_cadena(cadenaA, ret"+contador+".indice);"+"\n"+
                "\t"+"	//------------------------------------------"+"\n"+
                "");
                return metodo;
            }//-----------------------------------------------------------------
            //char -------------------------------------------------------------
            Retorno_Funcion ret13 = DefCocol.expect(DefCocol.character, cadenita);
            if(ret13.aceptado==true && ret13.cadena.length()==3){
                String cadena = "{"+(int)(ret13.cadena.charAt(1))+"}";
                metodo=("" +"\n"+
                "\t"+"	//------------------------------------------"+"\n"+
                "\t"+"	// "+ret13.cadena+" es un char"+"\n"+
                "\t"+"	String regex"+contador+" = \""+ret13.cadena.substring(1,ret13.cadena.length()-1)+"\";"+"\n"+
                "\t"+"	Retorno_Funcion ret"+contador+" = this.expect(regex"+contador+",cadenaA);"+"\n"+
                "\t"+"	if(ret"+contador+".aceptado==false){"+"\n"+
                "\t"+"		return new Retorno_Funcion();"+"\n"+
                "\t"+"	}"+"\n"+
                "\t"+"	cadenaA = Complementar_cadena(cadenaA, ret"+contador+".indice);"+"\n"+
                "\t"+"	//------------------------------------------"+"\n"+
                "");
                return metodo;
            }//-----------------------------------------------------------------
        }
        //----------------------------------------------------------------------
        //(TokenExpr)
        String cadena2 = cadenita;
        Retorno_Funcion ret2 = DefCocol.expect(DefCocol.space+"\\("+DefCocol.space, cadena2);
        cadena2 = DefCocol.Complementar_cadena(cadena2, ret2.indice);
        Retorno_Funcion ret21 = DefCocol.TokenExpr(cadena2);
        cadena2 = DefCocol.Complementar_cadena(cadena2, ret21.indice);
        Retorno_Funcion ret22 = DefCocol.expect(DefCocol.space+"\\)"+DefCocol.space, cadena2);
        if(ret2.aceptado==true && ret21.aceptado==true && ret22.aceptado==true){
            Main.PrintDB("Hay un TokenExpr en ()");
               metodo=("" +"\n"+
                "\t"+"	//------------------------------------------"+"\n"+
                "\t"+"	// (TokenExpr)\n"+
                "\t"+"	// Revisa: "+ret21.cadena+" en FuncionTokenExpr"+this.contador_TokenExpr+"\n"+
                "\t"+"	Retorno_Funcion ret"+contador+" = this.FuncionTokenExpr"+this.contador_TokenExpr+"(cadenaA);"+"\n"+
                "\t"+"	if(ret"+contador+".aceptado==false){"+"\n"+
                "\t"+"		return new Retorno_Funcion();"+"\n"+
                "\t"+"	}"+"\n"+
                "\t"+"	cadenaA = Complementar_cadena(cadenaA, ret"+contador+".indice);"+"\n"+
                "\t"+"	//------------------------------------------"+"\n"+
                "");
               this.Generar_Metodo_TokenExpr("FuncionTokenExpr"+this.contador_TokenExpr++, ret21.cadena);
               return metodo;
        }
        //----------------------------------------------------------------------
        //----------------------------------------------------------------------
        //[TokenExpr]
        String cadena3 = cadenita;
        Retorno_Funcion ret3 = DefCocol.expect(DefCocol.space+"\\["+DefCocol.space, cadena3);
        cadena3 = DefCocol.Complementar_cadena(cadena3, ret3.indice);
        Retorno_Funcion ret31 = DefCocol.TokenExpr(cadena3);
        cadena3 = DefCocol.Complementar_cadena(cadena3, ret31.indice);
        Retorno_Funcion ret32 = DefCocol.expect(DefCocol.space+"\\]"+DefCocol.space, cadena3);
        if(ret3.aceptado==true && ret3.aceptado==true && ret3.aceptado==true){
            Main.PrintDB("Hay un TokenExpr en []");
               metodo=("" +"\n"+
                "\t"+"	//------------------------------------------"+"\n"+
                "\t"+"	// [TokenExpr]\n"+
                "\t"+"	// Revisa: "+ret31.cadena+" en FuncionTokenExpr"+this.contador_TokenExpr+"\n"+
                "\t"+"	Retorno_Funcion ret"+contador+" = this.FuncionTokenExpr"+this.contador_TokenExpr+"(cadenaA);"+"\n"+
                "\t"+"	if(ret"+contador+".aceptado==true){"+"\n"+
                "\t"+"		cadenaA = this.Complementar_cadena(cadenaA, ret"+contador+".indice);"+"\n"+
                "\t"+"	}"+"\n"+
                "\t"+"	//cadenaA = Complementar_cadena(cadenaA, ret"+contador+".indice);"+"\n"+
                "\t"+"	//------------------------------------------"+"\n"+
                "");
               this.Generar_Metodo_TokenExpr("FuncionTokenExpr"+this.contador_TokenExpr++, ret31.cadena);
               return metodo;
        }
        //----------------------------------------------------------------------
        //----------------------------------------------------------------------
        //{TokenExpr}
        String cadena4 = cadenita;
        Retorno_Funcion ret4 = DefCocol.expect(DefCocol.space+"\\{"+DefCocol.space, cadena4);
        cadena4 = DefCocol.Complementar_cadena(cadena4, ret4.indice);
        Retorno_Funcion ret41 = DefCocol.TokenExpr(cadena4);
        cadena4 = DefCocol.Complementar_cadena(cadena4, ret41.indice);
        Retorno_Funcion ret42 = DefCocol.expect(DefCocol.space+"\\}"+DefCocol.space, cadena4);
        if(ret4.aceptado==true && ret4.aceptado==true && ret4.aceptado==true){
            Main.PrintDB("Hay un TokenExpr en {}");
               metodo=("" +"\n"+
                "\t"+"	//------------------------------------------"+"\n"+
                "\t"+"	// {TokenExpr}\n"+
                "\t"+"	// Revisa: "+ret41.cadena+" en FuncionTokenExpr"+this.contador_TokenExpr+"\n"+
                "\t"+"	Retorno_Funcion ret"+contador+" = new Retorno_Funcion();"+"\n"+
                "\t"+"	String cadena"+contador+" = cadenaA;"+"\n"+
                "\t"+"	while(true){"+"\n"+
                "\t"+"		Retorno_Funcion retB"+contador+" = this.FuncionTokenExpr"+this.contador_TokenExpr+"(cadena"+contador+");"+"\n"+
                "\t"+"		if(retB"+contador+".aceptado==false){"+"\n"+
                "\t"+"			break;"+"\n"+
                "\t"+"		}"+"\n"+
                "\t"+"		ret"+contador+".indice+= retB"+contador+".indice;"+"\n"+
                "\t"+"		ret"+contador+".cadena+= retB"+contador+".cadena;"+"\n"+
                "\t"+"		cadena"+contador+" = Complementar_cadena(cadena"+contador+", retB"+contador+".indice);"+"\n"+
                "\t"+"	}"+"\n"+
                "\t"+"	cadenaA = cadena"+contador+";"+"\n"+
                "\t"+"	//------------------------------------------"+"\n"+
                "");
               this.Generar_Metodo_TokenExpr("FuncionTokenExpr"+this.contador_TokenExpr++, ret41.cadena);
               return metodo;
        }
        //----------------------------------------------------------------------

        return "";
    }

}
